﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GbmpCommon.h"




namespace gcmp
{

    /// \brief 类ElementId用来表示Element在文档中的唯一标识.
    ///
    /// \see Element
    class GCMP_FOUNDATION_EXPORT ElementId
    {
    public:
        /// \brief 构造函数
        /// \param id  需要设置的id, 默认为-1
        FORCE_INLINE explicit ElementId(Int64 id=-1): m_id(id) {}

        /// \brief 析构函数
        FORCE_INLINE ~ElementId() {}

        /// \brief 拷贝构造函数
        FORCE_INLINE ElementId(const ElementId &other): m_id(other.m_id) {}
        
        /// \brief 赋值重载函数
        /// \return ElementId & 返回自身
        FORCE_INLINE ElementId& operator=(const ElementId &other) {m_id = other.m_id;return *this;}

        /// \brief 判断是否是有效的id
        /// \return bool true-有效的， false-无效的
        FORCE_INLINE bool IsValid() const{return m_id>=0;}

        /// \brief 获取当前ElementId的数值表示
        /// \return Int64 ElementId的数值
        FORCE_INLINE Int64 AsInt64() const{return m_id;}

        /// \brief 重载==符，判断两个ElementId的值是否相同
        /// \param elementId 需要对比的目标id
        /// \return bool true-相同， false-不同
        FORCE_INLINE bool operator==(const ElementId& elementId) const {return m_id == elementId.m_id;}

        /// \brief 重载!=符，判断两个ElementId的值是否不同
        /// \param elementId 需要对比的目标id
        /// \return bool true-不同， false-相同
        FORCE_INLINE bool operator!=(const ElementId& elementId)const {return m_id != elementId.m_id;}

        /// \brief 重载>符，判断两个ElementId的大小关系
        /// \param elementId 需要对比的目标id
        /// \return bool true-当前ElementId大于目标， false-当前ElementId小于目标
        FORCE_INLINE bool operator>(const ElementId& elementId)const {return m_id > elementId.m_id;}

        /// \brief 重载<符，判断两个ElementId的大小关系
        /// \param elementId 需要对比的目标id
        /// \return bool true-当前ElementId小于目标， false-当前ElementId大于目标
        FORCE_INLINE bool operator<(const ElementId& elementId)const {return m_id < elementId.m_id;}

    public:
        

        /// \brief 创建一个无效的ElementId
        /// \return 创建成功的ElementId
        static ElementId CreateInvalidId() { return InvalidID; }

        /// \brief 通过指定值创建一个ElementId
        /// \return 创建成功的ElementId
        static ElementId Create(Int64 id) { return ElementId(id); }

        /// \brief 获取当前ElementId的数值
        /// \return 当前ElementId的数值表示
        Int64 GetId() const {return m_id;}
        
        /// \brief 判断当前ElementId是否是有效的
        /// \return bool true-有效的， false-无效的
        bool GetIsValidId() const{return IsValid();}

        /// \brief 判断两个ElementId的值是否相同
        /// \param elementId 需要对比的目标id
        /// \return bool true-相同， false-不同
        bool HasSameValue(const ElementId& elementId) const { return (m_id == elementId.m_id); }

    public:
        static const ElementId InvalidID;
    private:
        Int64 m_id;
    };

    IMMORTAL_TYPE_NAME(ElementId);

    /// \brief 重载<<运算符, 宽字符
    /// \param os 流对象
    /// \param elemId 需要操作的ElementId
    /// \return std::wostream & 返回流对象
    FORCE_INLINE std::wostream& operator<<(std::wostream& os, ElementId elemId)
    {
        return os << elemId.AsInt64();
    }

    /// \brief 重载<<运算符
    /// \param os 流对象
    /// \param elemId 需要操作的ElementId
    /// \return std::ostream & 返回流对象
    FORCE_INLINE std::ostream& operator<<(std::ostream& os, ElementId elemId)
    {
        return os << elemId.AsInt64();
    }

    /// \brief ElementId的hash值计算
    struct GCMP_FOUNDATION_EXPORT  ElementIdHash
    {
        std::size_t operator()(const ElementId& key) const
        {
            return std::hash<Int64>()(key.AsInt64());
        }
    };

    typedef std::vector<ElementId> ElementIdArray;
    typedef std::set<ElementId> ElementIdSet;
    typedef std::unordered_set<ElementId, ElementIdHash> UnorderedElementIdSet;
}




